﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="RelateTransactionViewModel.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Defines the RelateTransactionViewModel type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Windows.Client.ViewModel
{
    using System;
    using System.Collections.ObjectModel;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Windows.Data;
    using System.Windows.Input;
    using Business.Interfaces;
    using Common;
    using Hisaab.Common;

    using Microsoft.Practices.ServiceLocation;

    using Model;

    /// <summary>
    /// Defines the <seealso cref="Hisaab.Windows.Client.ViewModel.RelateTransactionViewModel"/> type.
    /// </summary>
    public class RelateTransactionViewModel : DialogViewModel
    {
        /// <summary>
        /// The source transaction. This transaction will always be debit
        /// </summary>
        private readonly Transaction _sourceTransaction;

        /// <summary>
        /// Account manager object
        /// </summary>
        private readonly IAccountManager _accountManager;

        /// <summary>
        /// Transaction Manager object
        /// </summary>
        private readonly ITransactionManager _transactionManager;

        private readonly ISession _session;

        /// <summary>
        /// Query delegate command
        /// </summary>
        private DelegateCommand _queryCommand;

        /// <summary>
        /// The selected transaction to link to
        /// </summary>
        private Transaction _selectedTransaction;

        /// <summary>
        /// Accounts list
        /// </summary>
        private CollectionView _accounts;

        /// <summary>
        /// Backing field for Selected Account
        /// </summary>
        private int _selectedAccount;

        /// <summary>
        /// Backing field for start date
        /// </summary>
        private DateTime _startDate;

        /// <summary>
        /// Backing field for end date
        /// </summary>
        private DateTime _endDate;

        /// <summary>
        /// Transactions list
        /// </summary>
        private ObservableCollection<Transaction> _transactions;

        /// <summary>
        /// Initializes a new instance of the <see cref="RelateTransactionViewModel"/> class.
        /// </summary>
        /// <param name="sourceTransaction">The source transaction. This transaction will always be debit</param>
        public RelateTransactionViewModel(Transaction sourceTransaction)
            : this(
            sourceTransaction,
            ServiceLocator.Current.GetInstance<IAccountManager>(),
            ServiceLocator.Current.GetInstance<ITransactionManager>(),
            ServiceLocator.Current.GetInstance<ISession>())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RelateTransactionViewModel"/> class.
        /// </summary>
        /// <param name="sourceTransaction">The source transaction.</param>
        /// <param name="accountManager">The account manager.</param>
        /// <param name="transactionManager">The transaction manager.</param>
        /// <param name="session">The session</param>
        public RelateTransactionViewModel(Transaction sourceTransaction, IAccountManager accountManager, ITransactionManager transactionManager, ISession session)
        {
            Contract.Requires<ArgumentNullException>(sourceTransaction != null);
            Contract.Requires<ArgumentNullException>(accountManager != null);
            Contract.Requires<ArgumentNullException>(transactionManager != null);
            Contract.Requires<ArgumentNullException>(session != null);

            _sourceTransaction = sourceTransaction;
            _accountManager = accountManager;
            _transactionManager = transactionManager;
            _session = session;

            StartDate = _sourceTransaction.Date.AddDays(-2);
            EndDate = _sourceTransaction.Date.AddDays(2);
        }

        /// <summary>
        /// Gets the new tag command.
        /// </summary>
        public ICommand QueryCommand
        {
            get
            {
                if (_queryCommand == null)
                {
                    _queryCommand = new DelegateCommand(LoadTransactions, CanLoadTransaction);
                }

                return _queryCommand;
            }
        }

        /// <summary>
        /// Gets the Account Types.
        /// </summary>
        public CollectionView Accounts
        {
            get
            {
                if (_accounts == null)
                {
                    _accounts = new CollectionView(
                        _accountManager
                            .List(new Business.Entities.Account { UserId = _session.LoggedUser })
                            .Select(x => x.Map<Business.Entities.Account, Account>()));
                }

                return _accounts;
            }
        }

        /// <summary>
        /// Gets or sets the selected account.
        /// </summary>
        /// <value>
        /// The selected account.
        /// </value>
        public int SelectedAccount
        {
            get
            {
                return _selectedAccount;
            }

            set
            {
                if (_selectedAccount != value)
                {
                    _selectedAccount = value;
                    OnPropertyChanged("SelectedAccount");
                }
            }
        }

        /// <summary>
        /// Gets or sets the start date.
        /// </summary>
        /// <value>
        /// The start date.
        /// </value>
        public DateTime StartDate
        {
            get
            {
                return _startDate;
            }

            set
            {
                if (_startDate != value)
                {
                    _startDate = value;
                    OnPropertyChanged("StartDate");
                }
            }
        }

        /// <summary>
        /// Gets or sets the end date.
        /// </summary>
        /// <value>
        /// The end date.
        /// </value>
        public DateTime EndDate
        {
            get
            {
                return _endDate;
            }

            set
            {
                if (_endDate != value)
                {
                    _endDate = value;
                    OnPropertyChanged("EndDate");
                }
            }
        }

        /// <summary>
        /// Gets the transactions.
        /// </summary>
        public ObservableCollection<Transaction> Transactions
        {
            get
            {
                return _transactions;
            }

            private set
            {
                if (value != _transactions)
                {
                    _transactions = value;
                    OnPropertyChanged("Transactions");
                }
            }
        }

        /// <summary>
        /// Gets or sets the selected transaction.
        /// </summary>
        /// <value>
        /// The selected transaction.
        /// </value>
        public Transaction SelectedTransaction
        {
            get
            {
                return _selectedTransaction;
            }

            set
            {
                if (_selectedTransaction != value)
                {
                    _selectedTransaction = value;
                    OnPropertyChanged("SelectedTransaction");
                }
            }
        }

        /// <summary>
        /// Loads the transactions.
        /// </summary>
        public void LoadTransactions()
        {
            var transactionFilter = new Business.Entities.TransactionFilter
                                        {
                                            SortBy = Business.Entities.SortByType.Date,
                                            OrderBy = Business.Entities.OrderByType.Ascending,
                                            StartDate = StartDate,
                                            EndDate = EndDate
                                        };

            var filteredList = _transactionManager.FilteredList(transactionFilter, SelectedAccount)
                .Where(x => x.TransactionId != _sourceTransaction.TransactionId)
                .Select(x => x.Map<Business.Entities.Transaction, Transaction>());
            Transactions = new ObservableCollection<Transaction>(filteredList);
        }

        /// <summary>
        /// Determines whether this instance [can load transaction].
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance [can load transaction]; otherwise, <c>false</c>.
        /// </returns>
        public bool CanLoadTransaction()
        {
            return SelectedAccount > 0;
        }

        /// <summary>
        /// Called when [ok pressed].
        /// </summary>
        /// <returns>
        /// True if dialog to be closed, false to avoid closing
        /// </returns>
        public override bool? OnOkDialog()
        {
            _transactionManager.RelateTransactions(_sourceTransaction.TransactionId, SelectedTransaction.TransactionId);
            return true;
        }

        /// <summary>
        /// Determines whether this instance [can ok comand].
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance [can ok comand]; otherwise, <c>false</c>.
        /// </returns>
        public override bool CanOkComand()
        {
            return SelectedTransaction != null;
        }
    }
}